home
diamond Go Premium
Data Engineering Path  ·  Data Modelling
FACEBOOK CASE STUDY

// ============================================ // FACEBOOK DATA MODEL - DBML FORMAT // Use at: https://dbdiagram.io/ // ============================================

// ============================================ // CORE ENTITY: USERS // ============================================

Table users { user_id int [pk, increment] email varchar(100) [unique, not null] password_hash varchar(255) [not null] first_name varchar(50) [not null] last_name varchar(50) [not null] username varchar(50) [unique] date_of_birth date [not null, note: 'Must be 13+'] gender varchar(20) profile_picture_url varchar(500) cover_photo_url varchar(500) bio text location varchar(100) hometown varchar(100) relationship_status varchar(50) created_at timestamp [default: CURRENT_TIMESTAMP] is_active boolean [default: true] is_verified boolean [default: false] friends_count int [default: 0, note: 'Denormalized']

Indexes { email username (first_name, last_name) }

Note: 'Platform users with rich profile information' }

// ============================================ // FRIENDSHIPS (Bidirectional) // ============================================

Table friendships { friendship_id int [pk, increment] user_id_1 int [not null, ref: > users.user_id] user_id_2 int [not null, ref: > users.user_id] created_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { user_id_1 user_id_2 (user_id_1, user_id_2) [unique, note: 'Prevent duplicate friendships'] }

Note: 'Bidirectional friendships - mutual connections' }

Table friend_requests { request_id int [pk, increment] sender_id int [not null, ref: > users.user_id] receiver_id int [not null, ref: > users.user_id] status varchar(20) [default: 'pending', note: 'pending, accepted, rejected'] requested_at timestamp [default: CURRENT_TIMESTAMP] responded_at timestamp [null]

Indexes { sender_id receiver_id status (sender_id, receiver_id) [unique, note: 'One request per pair'] }

Note: 'Friend request management - accepted creates friendship' }

// ============================================ // CONTENT: POSTS // ============================================

Table posts { post_id bigint [pk, increment] user_id int [not null, ref: > users.user_id] group_id int [ref: > groups.group_id, note: 'If posted in group'] page_id int [ref: > pages.page_id, note: 'If posted on page'] content text [not null] post_type varchar(20) [default: 'status', note: 'status, photo, video, link, share'] privacy_level varchar(20) [default: 'friends', note: 'public, friends, custom'] location varchar(100) feeling varchar(50) created_at timestamp [default: CURRENT_TIMESTAMP] updated_at timestamp [default: CURRENT_TIMESTAMP] is_deleted boolean [default: false] reactions_count int [default: 0] comments_count int [default: 0] shares_count int [default: 0]

Indexes { user_id group_id page_id created_at (user_id, created_at) [note: 'User timeline'] }

Note: 'User-generated content on timelines, groups, and pages' }

// ============================================ // ENGAGEMENT: REACTIONS // ============================================

Table reactions { reaction_id bigint [pk, increment] user_id int [not null, ref: > users.user_id] post_id bigint [not null, ref: > posts.post_id] reaction_type varchar(20) [not null, note: 'like, love, haha, wow, sad, angry'] created_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { user_id post_id (user_id, post_id) [unique, note: 'One reaction per user per post'] }

Note: 'Facebook reactions - 6 types: Like, Love, Haha, Wow, Sad, Angry' }

// ============================================ // ENGAGEMENT: COMMENTS // ============================================

Table comments { comment_id bigint [pk, increment] post_id bigint [not null, ref: > posts.post_id] user_id int [not null, ref: > users.user_id] parent_comment_id bigint [ref: > comments.comment_id, note: 'For nested replies'] content text [not null] created_at timestamp [default: CURRENT_TIMESTAMP] updated_at timestamp [default: CURRENT_TIMESTAMP] is_deleted boolean [default: false] reactions_count int [default: 0, note: 'Comments can be reacted to']

Indexes { post_id user_id parent_comment_id }

Note: 'Nested comments - self-referencing for threaded discussions' }

// ============================================ // ENGAGEMENT: SHARES // ============================================

Table shares { share_id bigint [pk, increment] user_id int [not null, ref: > users.user_id] post_id bigint [not null, ref: > posts.post_id] shared_to_group_id int [ref: > groups.group_id] share_comment text shared_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { user_id post_id }

Note: 'Post shares to timeline or groups' }

// ============================================ // COMMUNITIES: GROUPS // ============================================

Table groups { group_id int [pk, increment] name varchar(200) [not null] description text privacy_type varchar(20) [default: 'public', note: 'public, private, secret'] created_by int [not null, ref: > users.user_id] cover_photo_url varchar(500) created_at timestamp [default: CURRENT_TIMESTAMP] members_count int [default: 0]

Indexes { name created_by }

Note: 'Communities and interest-based groups' }

Table group_members { membership_id int [pk, increment] group_id int [not null, ref: > groups.group_id] user_id int [not null, ref: > users.user_id] role varchar(20) [default: 'member', note: 'admin, moderator, member'] joined_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { group_id user_id (group_id, user_id) [unique] }

Note: 'Group membership with roles' }

// ============================================ // BUSINESS: PAGES // ============================================

Table pages { page_id int [pk, increment] name varchar(200) [not null] category varchar(100) description text profile_picture_url varchar(500) cover_photo_url varchar(500) website varchar(200) created_at timestamp [default: CURRENT_TIMESTAMP] followers_count int [default: 0]

Indexes { name category }

Note: 'Business and brand pages' }

Table page_followers { follower_id int [pk, increment] page_id int [not null, ref: > pages.page_id] user_id int [not null, ref: > users.user_id] followed_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { page_id user_id (page_id, user_id) [unique] }

Note: 'Users follow pages (not friend)' }

// ============================================ // EVENTS // ============================================

Table events { event_id int [pk, increment] name varchar(200) [not null] description text location varchar(200) start_time datetime [not null] end_time datetime created_by int [not null, ref: > users.user_id] group_id int [ref: > groups.group_id] page_id int [ref: > pages.page_id] privacy_type varchar(20) [default: 'public'] cover_photo_url varchar(500) created_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { created_by group_id page_id start_time }

Note: 'Social events and gatherings' }

Table event_attendees { attendee_id int [pk, increment] event_id int [not null, ref: > events.event_id] user_id int [not null, ref: > users.user_id] rsvp_status varchar(20) [default: 'interested', note: 'going, interested, not_going'] responded_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { event_id user_id (event_id, user_id) [unique] }

Note: 'Event RSVPs with status' }

// ============================================ // MEDIA: PHOTOS // ============================================

Table photo_albums { album_id int [pk, increment] user_id int [not null, ref: > users.user_id] name varchar(200) [not null] description text privacy_level varchar(20) [default: 'friends'] created_at timestamp [default: CURRENT_TIMESTAMP] photos_count int [default: 0]

Indexes { user_id }

Note: 'Photo collections/albums' }

Table photos { photo_id bigint [pk, increment] user_id int [not null, ref: > users.user_id] album_id int [ref: > photo_albums.album_id] post_id bigint [ref: > posts.post_id] photo_url varchar(500) [not null] caption text created_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { user_id album_id post_id }

Note: 'Individual photos' }

Table photo_tags { tag_id bigint [pk, increment] photo_id bigint [not null, ref: > photos.photo_id] user_id int [not null, ref: > users.user_id] created_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { photo_id user_id (photo_id, user_id) [unique] }

Note: 'People tagged in photos' }

// ============================================ // MESSAGING // ============================================

Table conversations { conversation_id bigint [pk, increment] is_group_chat boolean [default: false] name varchar(200) [note: 'Optional group chat name'] created_at timestamp [default: CURRENT_TIMESTAMP]

Note: 'Message threads (1-on-1 or group)' }

Table conversation_participants { participant_id bigint [pk, increment] conversation_id bigint [not null, ref: > conversations.conversation_id] user_id int [not null, ref: > users.user_id] joined_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { conversation_id user_id (conversation_id, user_id) [unique] }

Note: 'Users in conversations' }

Table messages { message_id bigint [pk, increment] conversation_id bigint [not null, ref: > conversations.conversation_id] sender_id int [not null, ref: > users.user_id] content text [not null] sent_at timestamp [default: CURRENT_TIMESTAMP] is_read boolean [default: false]

Indexes { conversation_id sender_id sent_at }

Note: 'Individual messages in conversations' }

// ============================================ // NOTIFICATIONS // ============================================

Table notifications { notification_id bigint [pk, increment] user_id int [not null, ref: > users.user_id] type varchar(50) [not null, note: 'friend_request, post_reaction, comment, event_invite, etc.'] actor_user_id int [ref: > users.user_id] related_id bigint [note: 'ID of related entity'] is_read boolean [default: false] created_at timestamp [default: CURRENT_TIMESTAMP]

Indexes { user_id is_read created_at }

Note: 'Activity notifications' }

// ============================================ // RELATIONSHIP SUMMARY // ============================================

// Bidirectional Relationships: // - users <-> users (via friendships)

// One-to-Many: // - users -> posts // - users -> groups (created_by) // - groups -> posts // - pages -> posts // - posts -> comments // - comments -> comments (nested)

// Many-to-Many: // - users <-> groups (via group_members) // - users <-> pages (via page_followers) // - users <-> events (via event_attendees) // - users <-> posts (via reactions) // - users <-> photos (via photo_tags) // - users <-> conversations (via conversation_participants)

// ============================================ // KEY FEATURES // ============================================

// 1. Bidirectional Friendships (unlike Twitter's follow) // 2. Friend Requests (pending/accepted/rejected) // 3. Multiple Reaction Types (6 types) // 4. Nested Comments (self-referencing) // 5. Groups with Roles (admin/moderator/member) // 6. Pages (business presence) // 7. Events with RSVPs // 8. Photo Albums and Tagging // 9. Group Chats (conversations) // 10. Privacy Levels (public/friends/custom)

Find this content helpful? ☕ Buy me a coffee

Entity Details

Create New Item

help

Submit Technical Query

Have a question or run into an issue? Describe it below, upload an optional screenshot, and our engineering team will answer it!

image Attach image (optional)

Submit Feedback

build Free Developer Utility Free Tool
gavel

Privacy & Legal Disclaimer

1. Client-Side Browser Processing

All utility tools on DeepEngineerHub (including Image to PDF, Text Formatters, JSON Converters, and Encryptors) execute 100% locally within your client browser using WebAssembly and JavaScript. No uploaded images, text, or documents are transmitted, collected, or stored on remote servers.

2. Limitation of Liability ("As-Is" Provision)

Tools and services are provided free of charge for convenience and educational purposes "as-is" without warranties of any kind. DeepEngineerHub shall not be held liable for any data loss, formatting inconsistencies, or indirect damages resulting from tool usage.

3. Open Source & Third-Party Software

Certain utilities utilize open-source client libraries (such as jsPDF, Mermaid.js, Pyodide) licensed under MIT, Apache, or BSD open licenses. All intellectual property remains with their respective copyright holders.